//
//  MainView.m
//  ipaInstaller
//
//  Created by Aruisi on 2016/10/31.
//  Copyright © 2016年 ushareit. All rights reserved.
//

#import <CommonCrypto/CommonDigest.h> 
#import <CoreImage/CoreImage.h>
#import "MainView.h"
#import "GCDWebServer.h"
#import "GCDWebServerFileResponse.h"
#import "GCDWebServerDataResponse.h"
#import "ZipFile.h"
#import "FileInZipInfo.h"
#import "ZipReadStream.h"

NSString* model = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n"
"<dict>\n"
"   <key>items</key>\n"
"   <array>\n"
"       <dict>\n"
"           <key>assets</key>\n"
"           <array>\n"
"               <dict>\n"
"                   <key>kind</key>\n"
"                   <string>software-package</string>\n"
"                   <key>url</key>\n"
"                   <string>%@</string>\n"
"               </dict>\n"
"           </array>\n"
"           <key>metadata</key>\n"
"           <dict>\n"
"               <key>bundle-identifier</key>\n"
"               <string>%@</string>\n"
"               <key>bundle-version</key>\n"
"               <string>%@</string>\n"
"               <key>kind</key>\n"
"               <string>software</string>\n"
"               <key>title</key>\n"
"               <string>%@</string>\n"
"           </dict>\n"
"       </dict>\n"
"   </array>\n"
"</dict>\n"
"</plist>\n"
;

NSString* html = @"<a href=\"itms-services://?action=download-manifest&url=https://ssl.scorplot.com/%@.plist\">%@</a>";

@implementation MainView
{
    GCDWebServer* _server;
    NSDictionary* _ipa;
    BOOL isDragIn;
}

-(instancetype)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        _server = [[GCDWebServer alloc] init];
        
        __weak typeof(self) ws = self;
        [_server addHandlerForMethod:@"GET" path:@"/download.ipa" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(__kindof GCDWebServerRequest *request) {
            return [ws downloadIpa:request];
        }];
        
        [_server addHandlerForMethod:@"GET" path:@"/index.html" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(__kindof GCDWebServerRequest *request) {
            return [ws showHtml];
        }];
        
        
        [_server startWithPort:0 bonjourName:nil];
        
        [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
        
    }
    return self;
}

-(GCDWebServerResponse*)downloadIpa:(GCDWebServerRequest*)request{
    GCDWebServerResponse* response = nil;
    response = [GCDWebServerFileResponse responseWithFile:_ipa[@"file"] byteRange:request.byteRange isAttachment:YES];
    [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"];
    return response;

}

-(GCDWebServerResponse*)showHtml {
    NSString* temp = [NSString stringWithFormat:html, _ipa[@"md5"], _ipa[@"name"]];
    GCDWebServerResponse* response = [GCDWebServerDataResponse responseWithData:[temp dataUsingEncoding:NSUTF8StringEncoding] contentType:@"text/html"];
    return response;
}

//static NSString* MD5(NSString* filePath) {
//    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:filePath];
//    if( handle== nil ) {
//        return nil;
//    }
//    CC_MD5_CTX md5;
//    CC_MD5_Init(&md5);
//    BOOL done = NO;
//    while(!done)
//    {
//        NSData* fileData = [handle readDataOfLength: 256 ];
//        CC_MD5_Update(&md5, [fileData bytes], [fileData length]);
//        if( [fileData length] == 0 ) done = YES;
//    }
//    unsigned char digest[CC_MD5_DIGEST_LENGTH];
//    CC_MD5_Final(digest, &md5);
//    NSString* s = [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
//                   digest[0], digest[1],
//                   digest[2], digest[3],
//                   digest[4], digest[5],
//                   digest[6], digest[7],
//                   digest[8], digest[9],
//                   digest[10], digest[11],
//                   digest[12], digest[13],
//                   digest[14], digest[15]];
//    
//    return s;
//}
//
//static NSString* getMD5WithData(NSData * data){
//    const char* original_str = (const char *)[data bytes];
//    unsigned char digist[CC_MD5_DIGEST_LENGTH]; //CC_MD5_DIGEST_LENGTH = 16
//    CC_MD5(original_str, (uint)strlen(original_str), digist);
//    NSMutableString* outPutStr = [NSMutableString stringWithCapacity:10];
//    for(int  i =0; i<CC_MD5_DIGEST_LENGTH;i++){
//        [outPutStr appendFormat:@"%02x",digist[i]];//小写x表示输出的是小写MD5，大写X表示输出的是大写MD5
//    }
//    
//    //也可以定义一个字节数组来接收计算得到的MD5值
//    //    Byte byte[16];
//    //    CC_MD5(original_str, strlen(original_str), byte);
//    //    NSMutableString* outPutStr = [NSMutableString stringWithCapacity:10];
//    //    for(int  i = 0; i<CC_MD5_DIGEST_LENGTH;i++){
//    //        [outPutStr appendFormat:@"%02x",byte[i]];
//    //    }
//    //    [temp release];
//    
//    return [outPutStr lowercaseString];
//    
//}

static NSString* getmd5WithString(NSString * string)
{
    const char* original_str=[string UTF8String];
    unsigned char digist[CC_MD5_DIGEST_LENGTH]; //CC_MD5_DIGEST_LENGTH = 16
    CC_MD5(original_str, (uint)strlen(original_str), digist);
    NSMutableString* outPutStr = [NSMutableString stringWithCapacity:10];
    for(int  i =0; i<CC_MD5_DIGEST_LENGTH;i++){
        [outPutStr appendFormat:@"%02x", digist[i]];//小写x表示输出的是小写MD5，大写X表示输出的是大写MD5
    }
    return [outPutStr lowercaseString];
}

- (NSDictionary*)analysisIPA:(NSString*)filePath {
    NSDictionary* dic = nil;
    
    NSRegularExpression* reg = [[NSRegularExpression alloc] initWithPattern:@"^Payload/(.+?)\\.app/Info\\.plist$" options:NSRegularExpressionCaseInsensitive error:nil];
    
    NSString* appName = nil;
    NSDictionary* plist = nil;
    
    
    ZipFile *zFile = [[ZipFile alloc] initWithFileName:filePath mode:ZipFileModeUnzip];
    [zFile goToFirstFileInZip];
    BOOL bContinue = YES;
    
    while (bContinue) {
        
        FileInZipInfo *fInfo = [zFile currentFileInZipInfo];
        NSString* name = fInfo.name;
        
        NSTextCheckingResult* result = [reg firstMatchInString:name options:0 range:NSMakeRange(0, name.length)];
        if (result) {
            appName = [name substringWithRange:[result rangeAtIndex:1]];
            ZipReadStream *readStream = [zFile readCurrentFileInZip];
            
            NSData* data = [readStream readDataOfLength:fInfo.length];
            
            [readStream finishedReading];
            
            NSPropertyListFormat format;
            plist = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:nil];

            bContinue = false;
        } else {
            bContinue = [zFile goToNextFileInZip];
        }
    }
    
    if (appName && plist) {
        NSString* CFBundleIdentifier = [plist valueForKey:@"CFBundleIdentifier"];
        NSString* CFBundleShortVersionString = [plist valueForKey:@"CFBundleShortVersionString"];
        NSString* CFBundleDisplayName = [plist valueForKey:@"CFBundleDisplayName"];
        if (CFBundleDisplayName.length == 0)
            CFBundleDisplayName = [plist valueForKey:@"CFBundleExecutable"];
        
        NSString* pContent = [NSString stringWithFormat:model, [NSString stringWithFormat:@"%@download.ipa", _server.serverURL], CFBundleIdentifier, CFBundleShortVersionString, CFBundleDisplayName];
        
        NSMutableDictionary* temp = [[NSMutableDictionary alloc] init];
        [temp setValue:CFBundleDisplayName forKey:@"name"];
        [temp setValue:filePath forKey:@"file"];
        [temp setValue:pContent forKey:@"plist"];
        [temp setValue:getmd5WithString([NSString stringWithFormat:@"%@\n%@",pContent,filePath]) forKey:@"md5"];
        dic = temp;
    }
    
    [zFile close];
    
    return dic;
}
/**
 *  根据字符串生成二维码 CIImage 对象
 *
 *  @param urlString 需要生成二维码的字符串
 *
 *  @return 生成的二维码
 */

CIImage * creatQRcodeWithUrlstring(NSString * urlString){
    // 1.实例化二维码滤镜
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    // 2.恢复滤镜的默认属性 (因为滤镜有可能保存上一次的属性)
    [filter setDefaults];
    // 3.将字符串转换成NSdata
    NSData *data  = [urlString dataUsingEncoding:NSUTF8StringEncoding];
    // 4.通过KVO设置滤镜, 传入data, 将来滤镜就知道要通过传入的数据生成二维码
    [filter setValue:data forKey:@"inputMessage"];
    //    [filter setValue:@"Q" forKey:@"inputCorrectionLevel"];
    // 5.生成二维码
    CIImage *outputImage = [filter outputImage];
    return outputImage;
}

/**
 *  改变图片大小 (正方形图片)
 *
 *  @param ciImage 需要改变大小的CIImage 对象的图片
 *  @param size    图片大小 (正方形图片 只需要一个数)
 *
 *  @return 生成的目标图片
 */
+(NSImage *)changeImageSizeWithCIImage:(CIImage *)ciImage andSize:(CGFloat)size{
    CGRect extent = CGRectIntegral(ciImage.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    
    // 创建bitmap;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(YES)}];
    CGImageRef bitmapImage = [context createCGImage:ciImage fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    
    // 保存bitmap到图片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    
    return [[NSImage alloc]initWithCGImage:scaledImage size:NSMakeSize(size, size)];
}

#pragma mark - Destination Operations

- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
{
    isDragIn = YES;
    [self setNeedsDisplay:YES];
    return NSDragOperationCopy;
}

- (void)draggingExited:(id<NSDraggingInfo>)sender
{
    isDragIn = NO;
    [self setNeedsDisplay:YES];
}

- (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender
{
    isDragIn = NO;
    [self setNeedsDisplay:YES];
    return YES;
}

- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
{
    if ([sender draggingSource] != self) {
        NSArray* filePaths = [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType];
        _ipa = [self analysisIPA:filePaths[0]];
        
        self.image = nil;
        if (_ipa) {
            [self postRequest];
        }
    }
    
    return YES;
}

-(void) postRequest {
    //1.资源字符串
    NSString *urlStr = @"https://ssl.scorplot.com/ipa.plist";
    //如果字符串里面含有中文要进行转码
    //urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    //2.设置请求路径
    NSURL *url = [NSURL URLWithString:urlStr];
    
    //3.创建请求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; // 默认就是GET请求
    request.timeoutInterval = 5; // 设置请求超时
    request.HTTPMethod = @"POST"; // 设置为POST请求
    
    //4.设置请求体
    NSString *param = [NSString stringWithFormat:@"md5=%@&content=%@", [_ipa[@"md5"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],[_ipa[@"plist"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    request.HTTPBody = [param dataUsingEncoding:NSUTF8StringEncoding];
    
    //5.发送请求
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {  // 当请求结束的时候调用
        if (connectionError == nil) {
            CIImage* ciimage = creatQRcodeWithUrlstring([NSString stringWithFormat:@"%@index.html", _server.serverURL]);
            self.image = [MainView changeImageSizeWithCIImage:ciimage andSize:300];
        } else {
            NSAlert *alert = [[NSAlert alloc] init];
            [alert addButtonWithTitle:@"知道了"];
            [alert setMessageText:@"网络错误"];
            [alert setInformativeText:[connectionError localizedDescription]];
            [alert setAlertStyle:NSWarningAlertStyle];
            [alert beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
                if (result == NSAlertFirstButtonReturn) {//响应第一个按钮被按下：name：firstname；
                    NSLog(@"Ok");
                }
                
                if (result == NSAlertSecondButtonReturn) {
                    NSLog(@"Cancel");
                }
                
                if (result == NSAlertThirdButtonReturn) {
                    NSLog(@"chenglibin1");
                }
            }];
        }
    }];
}

-(IBAction)orderOut:(id)sender {
    
}

@end
